home *** CD-ROM | disk | FTP | other *** search
- {$X+,V-,B-,I-}
- program Fsend; { Master / Sender }
-
- { Testprogram for the nwPEP unit / NwTP 0.6 API. (c) 1993,1995, R.Spronk }
-
- {$DEFINE noTRACE}
-
- uses dos,crt,nwMisc,nwBindry,nwConn,nwIPX,nwPEP;
-
- CONST IOSocket=$5678; { socket to transmit/receive on }
-
- Var ListenECB :Tecb; { ECB and header, to listen for acknowledgement }
- ListenPepHdr :TpepHeader;
-
- SendECB :Tecb; { ECB and header, used to send the data }
- SendPepHdr :TpepHeader;
-
- socket :word;
-
- SendDataBuffer :array[1..546] of byte; { SendDataBufferfer for data to be sent }
-
- ListenDataBuffer:array[1..8] of byte;
-
- AckReceived :boolean; { set to true within the ListenForAckESR }
-
- SendTransId :LongInt; { transactionID. This uniquely identifies
- the packet. The slave/receiver has to
- reply with the same transactionID in the
- header of the acknowledgement. Only if
- this number is the same as the transactioID
- of the sent packet, the pavket is considered
- successfully delivered. }
-
- NewStack:array[1..1024] of word; { !! used by ESR }
- StackBottom:word; { !! used by ESR }
-
- f:file;
-
-
- Procedure CheckError(err:boolean; errNbr:word);
- begin
- if err
- then begin
- writeln;
- CASE errNbr of
- $0100:writeln('IPX needs to be installed.');
- $0200:writeln('Error: can''t locate the spcified username.');
- $0201:begin
- writeln('The specified user has multiple connections.');
- writeln('This demonstation program doesn''t support multiple connections.');
- end;
- $0202:writeln('Error: can''t find the address of the supplied username.');
- $0204:writeln('Transfer aborted after 50 retries.');
- $0205:writeln('Key pressed: Transfer aborted.');
- $0206:writeln('The supplied file couldn''t be found. Please supply full path.');
- $0300:writeln('Error reading file.');
- $10FE:writeln('Error opening socket: Socket Table Is Full.');
- $10FF:writeln('Error opening socket: Socket is already open.');
- end; {case}
- IPXcloseSocket(IOsocket);
- close(f);
- halt(1);
- end;
- end;
-
- Function TimeOut(t1,t2:word;n:byte):boolean;
- { ticks t2 - ticks t1 > n seconds ? }
- Var lt1,lt2:LongInt;
- begin
- lt2:=t2;
- if t1>t2 then lt2:=lt2+$FFFF;
- TimeOut:=(lt2-t1)>(n*18);
- end;
-
-
- {$F+}
- Procedure ListenForAckHandler(Var p:TPecb);
- { Interrupts are turned off -and should remain turned off- }
- begin
- IF (ListenECB.CompletionCode<>0) { packet must be suucessfully received.. }
- or (ListenPepHdr.IPXhdr.packetType<>PEP_PACKET_TYPE) { of type PEP.. }
- or (ListenPepHdr.ClientType<>$EA) { of client type $EA }
- or (ListenPepHdr.TransactionID<>SendTransId) { with a correct clientID (of the packet the master sent) }
- then IPXListenForPacket(ListenECB) { Invalid packet => listen again }
- else AckReceived:=true; { valid packet => ACK received ! }
- end;
- {$F-}
-
- {$F+}
- Procedure ListenForAckESR; assembler;
- asm { ES:SI are the only valid registers when entering this procedure ! }
- { interrupts are turned off -and should remain turned off- }
- mov dx, seg stackbottom
- mov ds, dx
-
- mov dx,ss { setup of a new local stack }
- mov bx,sp { ss:sp copied to dx:bx}
- mov ax,ds
- mov ss,ax
- mov sp,offset stackbottom
- push dx { push old ss:sp on new stack }
- push bx
-
- push es { push es:si on stack as local vars }
- push si
- mov di,sp
-
- push ss { push address of local ptr on stack }
- push di
- CALL ListenForAckHandler
-
- add sp,4 { skip stack ptr-copy }
- pop bx { restore ss:sp from new stack }
- pop dx
- mov sp,bx
- mov ss,dx
- end;
- {$F-}
-
-
- Var dest:TinternetworkAddress;
- ticks,ticks2:word;
- retries :word;
-
- Uname,Fname:string;
- NbrOfConn:byte;
- connList:TconnectionList;
-
- p:byte;
- FileInfo:searchrec;
- FileSize:LongInt;
- BytesRead:word;
-
- TransferStartTicks,TransferEndTicks:word;
- OriginalFileSize:LongInt;
-
- begin
- If paramcount<>2
- then begin
- writeln('Usage: FSEND <username> <filename>');
- writeln('-The file will be sent to the workstation of the supplied username.');
- writeln('-Run FGET on that workstation to receive the file.');
- halt(1);
- end;
- Uname:=ParamStr(1);
- UpString(Uname);
- NbrOfConn:=0;
- GetObjectConnectionNumbers(Uname,OT_USER,NbrOfConn,connList);
- CheckError((nwConn.result>0) or (NbrOfConn=0),$200);
- CheckError(NbrOfConn>1,$0201);
-
- GetInternetAddress(connList[1],dest);
- CheckError(nwconn.result>0,$0202);
- dest.socket:=IOsocket;
-
- Fname:=ParamStr(2);
- Assign(f,Fname);
- Reset(f,1);
- CheckError(IOresult<>0,$0206);
-
-
- IpxInitialize;
- CheckError(nwIPX.result>0,$0100);
-
- socket:=IOSocket;
- IPXopenSocket(Socket,SHORT_LIVED_SOCKET);
- CheckError(nwIPX.result>0,$1000+nwIPX.result);
-
- { setup listening for ack }
- AckReceived:=False;
-
- PEPsetupListenECB(Addr(ListenForAckESR),IOsocket,@ListenDataBuffer,8,
- ListenPepHdr,ListenECB);
- IPXListenForPacket(ListenECB);
-
- { send initial packet with the name and size of the file to be sent. }
- findfirst(Fname,$FF,FileInfo);
- Move(FileInfo.size,SendDataBuffer[16],4);
- FileSize:=Fileinfo.size;
- p:=length(Fname);
- while (p>0) and (Fname[p]<>':') and (Fname[p]<>'\')
- do dec(p);
- If p>0
- then delete (Fname,1,p);
- Move(Fname[0],SendDataBuffer[1],15);
-
- PEPsetupSendECB(NIL,IOsocket,dest,@SendDataBuffer[1],512,
- SendPepHdr,SendECB);
- SendTransID:=1;
- SendPepHdr.ClientType:=$EA;
-
- OriginalFileSize:=FileSize;
- FileSize:=FileSize+512; { compensate length for information header }
-
- writeln('FSEND waiting for remote handshake. (any key to abort)');
-
- While Filesize>0
- do begin
- ackreceived:=false;
- SendPepHdr.TransactionId:=SendTransId;
- IPXsendPacket(SendECB);
- {$IFDEF TRACE}
- write('Packet#',SendTransID,' sent.');
- {$ENDIF}
- while sendECB.InuseFlag<>0
- do IPXrelinquishControl;
-
- IPXGetIntervalMarker(ticks);
- retries:=0;
- REPEAT
- IPXrelinquishcontrol;
- IPXGetIntervalMarker(ticks2);
- if (ticks2-ticks)>2
- then begin
- inc(retries);
- {$IFDEF TRACE}
- writeln;
- write('Timeout: resending packet#',SendTransID);
- {$ENDIF}
- IPXsendPacket(SendECB);
- while sendECB.InuseFlag<>0
- do IPXrelinquishControl;
- IPXGetIntervalMarker(ticks);
- end;
- CheckError(retries>50,$0204);
- CheckError(Keypressed,$0205);
- UNTIL AckReceived;
- if SendTransID=1
- then begin
- writeln('Handshake received. Starting file transfer.');
- IPXGetIntervalMarker(TransferStartTicks);
- end;
- {$IFDEF TRACE}
- writeln(' Ackn.#',ListenPepHdr.TransactionID,' received.');
- {$ENDIF}
- FileSize:=FileSize-512;
-
- { fill buffer with next block of data }
- IF FileSize>0
- then begin
- BlockRead(f,SendDataBuffer,512,bytesread);
- CheckError((bytesread<512) and (filesize<>bytesread),$0300);
- end;
-
- inc(SendTransID);
- IPXListenForPacket(ListenECB); { start listening for acks again }
- end;
- IPXGetIntervalMarker(TransferEndTicks);
- IPXcancelEvent(ListenECB);
- Writeln('Transfer completed.');
- writeln('Throughput: ', 18*OriginalFileSize/(TransferEndTicks-TransferStartTicks):4:2,' bps');
- IPXcloseSocket(IOsocket);
- close(f);
-
- end.